package com.wxc;

/**
 * @author wxc
 * @date 2021年08月28日 17:50
 */
public class LinkedHashMap<K, V> extends HashMap<K, V> {

    private LinkedEntry<K, V> first;
    private LinkedEntry<K, V> last;

    @Override
    protected Entry<K, V> createEntry(K key, V value, Entry<K, V> left, Entry<K, V> right, Entry<K, V> parent) {
        // 双向链表
        LinkedEntry<K, V> entry = new LinkedEntry<>(key, value, left, right, parent);
        if(first == null) first = last = entry;
        else {
            entry.prev = last;
            last.next = entry;
            last = entry;
        }
        return entry;
    }

    @Override
    public void clear() {
        last = first = null;
        super.clear();
    }

    @Override
    public void traversal(Visitor<K, V> visitor) {
        if (visitor == null || first == null) return;
        LinkedEntry<K, V> entry = first;
        while(entry != null) {
            boolean flag = visitor.visit(entry.key, entry.value);
            if(flag) break;
            entry = entry.next;
        }
    }



    @Override
    protected V remove(Entry<K, V> node) {
        if (node == null) return null;
        LinkedEntry<K, V> entry = (LinkedEntry<K, V>) node;
        LinkedEntry<K, V> prev = entry.prev;
        LinkedEntry<K, V> next = entry.next;

        if(prev == null) first = next;
        else prev.next = next;

        if(next == null) last = prev;
        else next.prev = prev;

        return super.remove(node);
    }

    @Override
    protected Entry<K, V> createEntry(K key, V value) {
        return createEntry(key,value,null,null,null);
    }

    @Override
    protected Entry<K, V> createEntry(K key, V value, Entry<K, V> parent) {
        return createEntry(key,value,null,null,parent);
    }

    private static class LinkedEntry<K, V> extends Entry<K, V> {

        LinkedEntry<K, V> prev;
        LinkedEntry<K, V> next;


        public LinkedEntry(K key, V value) {
            super(key, value);
        }

        public LinkedEntry(K key, V value, Entry<K, V> parent) {
            super(key, value, parent);
        }

        public LinkedEntry(K key, V value, Entry<K, V> left, Entry<K, V> right, Entry<K, V> parent) {
            super(key, value, left, right, parent);
        }
    }
}
